package com.gitee.chenyaohua.ext;


import com.gitee.chenyaohua.antlr.JSON5BaseVisitor;
import com.gitee.chenyaohua.antlr.JSON5Parser;
import com.gitee.chenyaohua.common.*;
import org.antlr.v4.runtime.tree.TerminalNode;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Json5ResolveVisitor extends JSON5BaseVisitor<JsonNode<?>> {


    @Override
    public JsonNode<?> visitJson5(JSON5Parser.Json5Context ctx) {
        JSON5Parser.ValueContext value = ctx.value();
        JSON5Parser.ObjContext obj = value.obj();
        JSON5Parser.ArrContext arr = value.arr();

        if(obj != null){
            return this.visit(obj);
        }

        if(arr != null){
            return this.visit(arr);
        }
        return null;
    }

    @Override
    public JsonNode<?> visitObj(JSON5Parser.ObjContext ctx) {
        Map<Serializable,JsonNode<?>> map = new HashMap<>();

        List<JSON5Parser.PairContext> pairs = ctx.pair();
        for (JSON5Parser.PairContext pair : pairs) {
            JSON5Parser.KeyContext key = pair.key();
            JSON5Parser.ValueContext value = pair.value();
            JsonNode<?> keyNode = this.visitKey(key);
            JsonNode<?> valueNode = this.visitValue(value);
            map.put((Serializable) keyNode.getData(),valueNode);
        }

        return new ObjectNode(map);
    }

    @Override
    public JsonNode<?> visitPair(JSON5Parser.PairContext ctx) {
        return super.visitPair(ctx);
    }

    @Override
    public JsonNode<?> visitKey(JSON5Parser.KeyContext ctx) {
        TerminalNode txt = ctx.STRING();
        TerminalNode literal = ctx.LITERAL();

        if(txt!=null){
            String text = txt.getText();
            return new TextNode(text);
        }

        if(literal!=null){
            String text = literal.getText();

            if(Boolean.TRUE.toString().equals(text)){
                return new BoolNode(Boolean.TRUE);
            }else if(Boolean.FALSE.toString().equals(text)){
                return new BoolNode(Boolean.FALSE);
            }

            return new BoolNode(null);
        }
        return new TextNode(null);
    }

    @Override
    public JsonNode<?> visitValue(JSON5Parser.ValueContext ctx) {
        JSON5Parser.ArrContext arr = ctx.arr();
        JSON5Parser.ObjContext obj = ctx.obj();
        TerminalNode literal = ctx.LITERAL();
        TerminalNode txt = ctx.STRING();
        if(txt!=null){
            String text = txt.getText();
            return new TextNode(text);
        }

        if(literal!=null){
            String text = literal.getText();

            if(Boolean.TRUE.toString().equals(text)){
                return new BoolNode(Boolean.TRUE);
            }else if(Boolean.FALSE.toString().equals(text)){
                return new BoolNode(Boolean.FALSE);
            }
            return new BoolNode(null);
        }

        if(obj != null){
            return this.visitObj(obj);
        }

        if(arr != null){
            return this.visitArr(arr);
        }

        return new TextNode(null);
    }

    @Override
    public JsonNode<?> visitArr(JSON5Parser.ArrContext ctx) {
        List<JsonNode<?>> list = new LinkedList<>();

        for (JSON5Parser.ValueContext valueContext : ctx.value()) {
            JsonNode<?> visit = this.visit(valueContext);
            list.add(visit);
        }

        return new ArrayNode(list);
    }
}
